#include "Subs.h"
#include "Input.h"
#include "StringTable.h"
#include "Session.h"
#include "BbsControlData.h"

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <device.h>
#include <unistd.h>

#pragma code-name("SUBSCODE");
#pragma rodata-name("SUBSCODE");
#pragma data-name("SUBSDATA");
#pragma bss-name("SUBSBSS");

#define FILEPATTERN_SUBBOARD		"sub-%05u"
void displayEditSubsMenu(void);
void initializeSubboards(void);
void createSubboard(void);
int openSubboard(int subboardNumber, subboard_t *subboard);
int saveSubboard(subIndexRec_t *subboardIndexRec, subboard_t *subboard);
void mergeMessageFiles(void);

void editSubs(void)
{
	bool brk = false;

	displayEditSubsMenu();

	while(!brk)
	{
		if(kbhit())
		{
			switch(cgetc())
			{
			case CH_F1:
				createSubboard();
				displayEditSubsMenu();
				break;
			case CH_F3:
				displayEditSubsMenu();
				break;
			case CH_F5:
				displayEditSubsMenu();
				break;
			case CH_F7:
				displayEditSubsMenu();
				break;
			case CH_F8:
				initializeSubboards();
				displayEditSubsMenu();
				break;
			case CH_F2:
				mergeMessageFiles();
				displayEditSubsMenu();
				break;
			case CH_STOP:
				brk = true;
				break;
			}
		}
	}	
}

void displayEditSubsMenu(void)
{
	outputFile(PLATFORM_ENCODING, OD_SCREEN, "subs.edit", &(bcd.dataDirectory));
}

int openSubboard(int subboardNumber, subboard_t *subboard)
{
	static FILE *file;
	static char oldDirectory[17];
	static char directory[17];
	static char filename[17];
	static int result;

	getcwd(oldDirectory, 17);
	getdevicedir(bcd.dataDirectory.device, directory, 17);
	chdir(directory);

	sprintf(filename, FILEPATTERN_SUBBOARD, subboardNumber);

	file = fopen(filename, "rb");

	result = 0;
	if(file != NULL)
	{
		if(fread(subboard, sizeof(subboard_t), 1, file)==1)
			result = subboardNumber;
	}

	chdir(oldDirectory);

	return result;
}

void createSubboard(void)
{
	static char temp[6];
	static char subboardName[21];
	static char subboardDesc[41];
	static int sigopUsernumber;
	static int subboardNumber;
	static int minSLRead, minSLPost, maxThreadCount;
	static subIndexRec_t tempSubboard;

	memset(subboardName, 0, 21);
	memset(subboardDesc, 0, 41);

	clrscr();

	outputString(PLATFORM_ENCODING, OD_SCREEN, CHX_YELLOW "Create Subboard" CRLF CRLF);

	outputString(PLATFORM_ENCODING, OD_SCREEN, CHX_GREEN "Board Number" CHX_WHITE ": " CHX_LGREEN);
	memset(temp, 0, 6);
	inputString(IO_NUMERIC, temp, 4, false);

	if(strlen(temp) > 0)
	{
		subboardNumber = atoi(temp);
		if(subboardNumber > 0)
		{
			memset(&tempSubboard, 0, sizeof(subIndexRec_t));
			memset(&_currentSubboard, 0, sizeof(subboard_t));
			openSubboard(subboardNumber, &_currentSubboard);
			
			if(_currentSubboard.subboardNumber == 0)
			{
				memset(&_currentSubboard, 0, sizeof(subboard_t));
				outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF CHX_GREEN "Board Name" CHX_WHITE ": " CHX_LGREEN);
				inputString(IO_ALPHA_NUMERIC, subboardName, 21, false);

				if(strlen(subboardName) > 0)
				{
					memset(subboardDesc, 0, 41);
					outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF CHX_GREEN "Board Description" CHX_WHITE":" CHX_LGREEN CRLF);
					inputString(IO_ANY_CHARACTER, subboardDesc, 39, false);

					if(strlen(subboardDesc) > 0)
					{
						strcat(_currentSubboard.description, subboardDesc);

						outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF);
						memset(subboardDesc, 0, 41);
						inputString(IO_ANY_CHARACTER, subboardDesc, 39, false);

						if(strlen(subboardDesc) > 0)
						{
							strcat(_currentSubboard.description, CRLF);
							strcat(_currentSubboard.description, subboardDesc);


							outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF);
							memset(subboardDesc, 0, 41);
							inputString(IO_ANY_CHARACTER, subboardDesc, 39, false);

							if(strlen(subboardDesc) > 0)
							{
								strcat(_currentSubboard.description, CRLF);
								strcat(_currentSubboard.description, subboardDesc);
							}
						}
					}

					outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF CHX_GREEN "Sigop Number" CHX_WHITE ": " CHX_LGREEN);
					memset(temp, 0, 6);
					inputString(IO_NUMERIC, temp, 5, false);

					if(strlen(temp) > 0)
					{
						sigopUsernumber = atoi(temp);
					}
					else
					{
						sigopUsernumber = 0;
					}

					outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF CHX_GREEN "Min Security to Read" CHX_WHITE "(0): " CHX_LGREEN);
					memset(temp, 0, 6);
					inputString(IO_NUMERIC, temp, 5, false);

					if(strlen(temp) > 0)
					{
						minSLRead = atoi(temp);
					}
					else
					{
						minSLRead = 0;
					}

					outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF CHX_GREEN "Min Security to Post " CHX_WHITE "(1): " CHX_LGREEN);
					memset(temp, 0, 6);
					inputString(IO_NUMERIC, temp, 5, false);

					if(strlen(temp) > 0)
					{
						minSLPost = atoi(temp);
					}
					else
					{
						minSLPost = 1;
					}

					outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF CHX_GREEN "Max Number of Threads" CHX_WHITE "(0): " CHX_LGREEN);
					memset(temp, 0, 6);
					inputString(IO_NUMERIC, temp, 5, false);

					if(strlen(temp) > 0)
					{
						maxThreadCount = atoi(temp);
					}
					else
					{
						maxThreadCount = 0;
					}
	
					strcpy(tempSubboard.name, subboardName);
					strcpy(tempSubboard.description, _currentSubboard.description);
					tempSubboard.subboardNumber = subboardNumber;

					strcpy(_currentSubboard.name, subboardName);
					_currentSubboard.subboardNumber = subboardNumber;
					_currentSubboard.minSecurityLevelRead = minSLRead;
					_currentSubboard.minSecurityLevelPost = minSLPost;
					_currentSubboard.maxThreadCount = maxThreadCount;
					_currentSubboard.directory.device = bcd.dataDirectory.device;
					_currentSubboard.directory.drive = bcd.dataDirectory.drive;
					strcpy(_currentSubboard.directory.enterDirectoryCommand, bcd.dataDirectory.enterDirectoryCommand);
					strcpy(_currentSubboard.directory.leaveDirectoryCommand, bcd.dataDirectory.leaveDirectoryCommand);

					saveSubboard(&tempSubboard, &_currentSubboard);
					outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF CHX_BLUE "Subboard saved" CHX_WHITE ".");
					pause(PLATFORM_ENCODING, OD_SCREEN);
					if(_connectState == CS_DISCONNECTED) return;
				}
			}
			else
			{
				outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF CHX_RED "Subboard already exists" CHX_WHITE "." CRLF);
				pause(PLATFORM_ENCODING, OD_SCREEN);
				if(_connectState != CS_DISCONNECTED) return;
			}
		}
	}
}

int saveSubboard(subIndexRec_t *subboardIndexRec, subboard_t *subboard)
{
	static FILE *file, *filein;
	static char oldDirectory[17];
	static char directory[17];
	static char filename[17];
	static bases_t bases;
	static subIndexRec_t temp;
	static int i;
	bool found;

	getcwd(oldDirectory, 17);
	getdevicedir(bcd.dataDirectory.device, directory, 17);
	chdir(directory);

	sprintf(filename, FILEPATTERN_SUBBOARD, subboardIndexRec->subboardNumber);

	file = fopen(filename, "wb");

	if(file != NULL)
	{
		if(fwrite(subboard, sizeof(subboard_t), 1, file) == 1)
		{
			fclose(file);

			remove("subsindex.bak");
			rename("subsindex", "subsindex.bak");
			sprintf(filename, "subsindex.bak");
			
			filein = fopen("subsindex.bak", "rb");
			if(filein != NULL)
			{
				if(fread(&bases, sizeof(bases_t), 1, filein))
				{
					found = false;
					for(i = 0; i < bases.subboardCount; ++i)
					{
						if(fread(&temp, sizeof(subIndexRec_t), 1, filein))
						{
							if(temp.subboardNumber == subboardIndexRec->subboardNumber)
							{
								found = true;
								break;
							}
						}
					}

				}
				fclose(file);
			}

			file = fopen("subsindex", "wb");
			filein = fopen("subsindex.bak", "rb");
			if(filein != NULL && file != NULL)
			{
				fread(&bases, sizeof(bases_t), 1, filein);

				if(!found) bases.subboardCount++;

				fwrite(&bases, sizeof(bases_t), 1, file);

				for(i = 0; i < (bases.subboardCount - (found ? 0 : 1)); ++i)
				{
					fread(&temp, sizeof(subIndexRec_t), 1, filein);
					if(!found || temp.subboardNumber != subboardIndexRec->subboardNumber)
					{
						fwrite(&temp, sizeof(subIndexRec_t), 1, file);
					}
					else if(found)
					{
						fwrite(subboardIndexRec, sizeof(subIndexRec_t), 1, file);
					}
				}

				if(!found) 
				{
					fwrite(subboardIndexRec, sizeof(subIndexRec_t), 1, file);
				}

				fclose(filein);
			}
		}

		fclose(file);
	}
	else
	{
		return -1;
	}
}

void initializeSubboards(void)
{
	static FILE *file;
	static char oldDirectory[17];
	static char directory[17];
	static char filename[17];
	static subIndexRec_t indexRecord;
	
	outputString(PLATFORM_ENCODING, OD_SCREEN, "Are you sure you want to\nreinitialize your subboards?");

	if(getYesNo() == 1)
	{
		// STEP 1, Create the Email subboard.
		_currentBases.subboardCount = 1;
		memset(&_currentSubboard, 0, sizeof(subboard_t));
		memset(&indexRecord, 0, sizeof(subIndexRec_t));
		strcpy(_currentSubboard.name, "EMail");
		strcpy(indexRecord.name, _currentSubboard.name);
		strcpy(_currentSubboard.description, "Private EMail Subboard");
		strcpy(indexRecord.description, _currentSubboard.description);
		_currentSubboard.sigopUsernumber = 1;
		_currentSubboard.directory.device = bcd.dataDirectory.device;
		_currentSubboard.directory.drive = bcd.dataDirectory.drive;
		strcpy(_currentSubboard.directory.enterDirectoryCommand, bcd.dataDirectory.enterDirectoryCommand);
		strcpy(_currentSubboard.directory.leaveDirectoryCommand, bcd.dataDirectory.leaveDirectoryCommand);

		// STEP 2, Save the Email subboard.
		getcwd(oldDirectory, 17);
		getdevicedir(bcd.dataDirectory.device, directory, 17);
		chdir(directory);

		sprintf(filename, "sub.00000");

		file = fopen(filename, "wb");

		if(file != NULL)
		{
			if(fwrite(&_currentSubboard, sizeof(subboard_t), 1, file) == 1)
			{
				fclose(file);
				outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF "Wrote Subboard file for EMail.");

				file = fopen("subsindex", "wb");

				if(file != NULL)
				{
					if(fwrite(&_currentBases, sizeof(bases_t), 1, file) == 1)
					{
						if(fwrite(&indexRecord, sizeof(subIndexRec_t), 1, file) == 1)
						{
							outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF "Wrote Subboard index file.");
						}
						else
						{
							outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF "Error writing subboard index file.");
						}
					}
					else
					{
						outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF "Error writing subboard index file.");
					}
				}
				else
				{
					outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF "Error writing subboard index file.");
				}
			}

			fclose(file);
		}
		else
		{
			outputString(PLATFORM_ENCODING, OD_SCREEN, CRLF "Error writing subboard file for email.");
		}

		chdir(oldDirectory);
	}
}

void getSubboardIdxRec(subIndexRec_t * subboardIdxRec, int subboard)
{
	static FILE *file;
	static char oldDirectory[17];
	static char directory[17];
	static char filename[17];
	static int i;

	getcwd(oldDirectory, 17);
	getdevicedir(bcd.dataDirectory.device, directory, 17);
	chdir(directory);
		
	file = fopen("subsindex", "rb");

	for(i = 0; i <= subboard; ++i)
	{
		fread(subboardIdxRec, sizeof(subIndexRec_t), 1, file);
	}
	
	fclose(file);

	chdir(oldDirectory);
}

void mergeMessageFile(char subboard, int thread, int message)
{
	static FILE *file, *fileBody;
	static char oldDirectory[17];
	static char directory[17];
	static char filename[17];
	static int i;
	static char buffer[2];

	buffer[1] = 0;

	getcwd(oldDirectory, 17);
	getdevicedir(bcd.dataDirectory.device, directory, 17);
	chdir(directory);

	sprintf(filename, FILEPATTERN_MSG, subboard, thread, message);
	file = fopen(filename, "ab");
	if(file != NULL)
	{
		printf("\nopened: %s", filename);
		sprintf(filename, FILEPATTERN_MSG_BODY, subboard, thread, message);
		fileBody = fopen(filename, "rb");
		if(fileBody != NULL)
		{
			printf("\n  opened: %s", filename);
			while(fread(buffer, 1, 1, fileBody))
			{
				fwrite(buffer, 1, 1, file);
				printf(buffer);
			}
			fclose(file);
			fclose(fileBody);
			remove(filename);
			printf("\n  Merged: %s", filename);
		}
		
	}
	fclose(file);

	chdir(oldDirectory);
}

void mergeMessageFiles(void)
{
	static char i;
	static int j, k;
	static subIndexRec_t subIdxRec;

	loadCurrents();

	for(i = 0; i < _currentBases.subboardCount; ++i)
	{
		getSubboardIdxRec(&subIdxRec, i);
		loadSubboard(subIdxRec.subboardNumber);
		for(j = 0; j < _currentSubboard.highThreadNumber; ++j)
		{
			loadThread(j, true, true);
			for(k = 0; k < _currentMsgThread.highMessageNumber; ++k)
			{
				mergeMessageFile(i, j, k);
			}
		}
	}
}